package qimao.com.edu.util;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.*;

/**
 * 文件操作工具类，提供文件读取、移动、创建和删除等功能
 */
public class FileUtils {

    /**
     * 读取文件内容为字符串（兼容Java 8）
     * @param filePath 文件路径
     * @return 文件内容字符串
     * @throws IOException 如果读取文件失败
     */
    public static String readFileToString(String filePath) throws IOException {
        Path path = Paths.get(filePath);
        try (BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
            StringBuilder content = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                content.append(line).append(System.lineSeparator());
            }
            // 移除最后添加的换行符
            if (content.length() > 0) {
                content.setLength(content.length() - System.lineSeparator().length());
            }
            return content.toString();
        }
    }

    /**
     * 读取文件内容为行列表（兼容Java 8）
     * @param filePath 文件路径
     * @return 行列表
     * @throws IOException 如果读取文件失败
     */
    public static List<String> readFileToLines(String filePath) throws IOException {
        List<String> lines = new ArrayList<>();
        try (BufferedReader reader = Files.newBufferedReader(Paths.get(filePath), StandardCharsets.UTF_8)) {
            String line;
            while ((line = reader.readLine()) != null) {
                lines.add(line);
            }
        }
        return lines;
    }

    /**
     * 写入字符串到文件（兼容Java 8）
     * @param content 内容
     * @param filePath 文件路径
     * @throws IOException 如果写入文件失败
     */
    public static void writeStringToFile(String content, String filePath) throws IOException {
        try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(filePath), StandardCharsets.UTF_8)) {
            writer.write(content);
        }
    }

    /**
     * 写入行列表到文件（兼容Java 8）
     * @param lines 行列表
     * @param filePath 文件路径
     * @throws IOException 如果写入文件失败
     */
    public static void writeLinesToFile(List<String> lines, String filePath) throws IOException {
        try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(filePath), StandardCharsets.UTF_8)) {
            for (String line : lines) {
                writer.write(line);
                writer.newLine();
            }
        }
    }

    /**
     * 移动文件（使用NIO，兼容Java 8）
     * @param sourcePath 源文件路径
     * @param targetPath 目标文件路径
     * @param replaceExisting 如果目标文件已存在是否替换
     * @return 移动成功返回true，否则返回false
     * @throws IOException 如果移动文件失败
     */
    public static boolean moveFile(String sourcePath, String targetPath, boolean replaceExisting) throws IOException {
        Path source = Paths.get(sourcePath);
        Path target = Paths.get(targetPath);
        
        if (replaceExisting && Files.exists(target)) {
            Files.delete(target);
        }
        
        Files.move(source, target, StandardCopyOption.REPLACE_EXISTING);
        return true;
    }

    /**
     * 复制文件（使用NIO，兼容Java 8）
     * @param sourcePath 源文件路径
     * @param targetPath 目标文件路径
     * @param replaceExisting 如果目标文件已存在是否替换
     * @return 复制成功返回true，否则返回false
     * @throws IOException 如果复制文件失败
     */
    public static boolean copyFile(String sourcePath, String targetPath, boolean replaceExisting) throws IOException {
        Path source = Paths.get(sourcePath);
        Path target = Paths.get(targetPath);
        
        if (replaceExisting && Files.exists(target)) {
            Files.delete(target);
        }
        
        Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
        return true;
    }

    /**
     * 创建新文件（如果不存在）
     * @param filePath 文件路径
     * @return 创建成功返回true，如果文件已存在返回false
     * @throws IOException 如果创建文件失败
     */
    public static boolean createFileIfNotExists(String filePath) throws IOException {
        Path path = Paths.get(filePath);
        if (Files.exists(path)) {
            return false;
        }
        
        Files.createFile(path);
        return true;
    }

    /**
     * 创建目录（如果不存在），包括所有必要的父目录
     * @param dirPath 目录路径
     * @return 创建成功返回true，如果目录已存在返回false
     * @throws IOException 如果创建目录失败
     */
    public static boolean createDirectoryIfNotExists(String dirPath) throws IOException {
        Path path = Paths.get(dirPath);
        if (Files.exists(path)) {
            return false;
        }
        
        Files.createDirectories(path);
        return true;
    }

    /**
     * 删除文件
     * @param filePath 文件路径
     * @return 删除成功返回true，如果文件不存在返回false
     * @throws IOException 如果删除文件失败
     */
    public static boolean deleteFile(String filePath) throws IOException {
        Path path = Paths.get(filePath);
        if (!Files.exists(path)) {
            return false;
        }
        
        Files.delete(path);
        return true;
    }

    /**
     * 递归删除目录及其所有内容（兼容Java 8）
     * @param dirPath 目录路径
     * @return 删除成功返回true，如果目录不存在返回false
     * @throws IOException 如果删除目录失败
     */
    public static boolean deleteDirectory(String dirPath) throws IOException {
        Path path = Paths.get(dirPath);
        if (!Files.exists(path)) {
            return false;
        }
        
        if (!Files.isDirectory(path)) {
            throw new IllegalArgumentException("Path is not a directory: " + dirPath);
        }
        
        // 递归删除目录中的所有内容
        try (DirectoryStream<Path> stream = Files.newDirectoryStream(path)) {
            for (Path entry : stream) {
                if (Files.isDirectory(entry)) {
                    deleteDirectory(entry.toString());
                } else {
                    Files.delete(entry);
                }
            }
        }
        
        // 删除空目录
        Files.delete(path);
        return true;
    }

    /**
     * 检查文件或目录是否存在
     * @param path 文件或目录路径
     * @return 存在返回true，否则返回false
     */
    public static boolean exists(String path) {
        return Files.exists(Paths.get(path));
    }

    /**
     * 检查路径是否为目录
     * @param path 路径
     * @return 是目录返回true，否则返回false
     */
    public static boolean isDirectory(String path) {
        return Files.isDirectory(Paths.get(path));
    }

    /**
     * 检查路径是否为文件
     * @param path 路径
     * @return 是文件返回true，否则返回false
     */
    public static boolean isFile(String path) {
        return Files.isRegularFile(Paths.get(path));
    }

    /**
     * 获取文件大小（字节）
     * @param filePath 文件路径
     * @return 文件大小（字节）
     * @throws IOException 如果获取文件大小失败
     */
    public static long getFileSize(String filePath) throws IOException {
        Path path = Paths.get(filePath);
        return Files.size(path);
    }

    /**
     * 获取目录下的所有文件（不递归）
     * @param dirPath 目录路径
     * @return 文件列表
     * @throws IOException 如果读取目录失败
     */
    public static List<File> listFiles(String dirPath) throws IOException {
        List<File> files = new ArrayList<>();
        try (DirectoryStream<Path> stream = Files.newDirectoryStream(Paths.get(dirPath))) {
            for (Path path : stream) {
                if (Files.isRegularFile(path)) {
                    files.add(path.toFile());
                }
            }
        }
        return files;
    }

    /**
     * 获取目录下的所有子目录（不递归）
     * @param dirPath 目录路径
     * @return 子目录列表
     * @throws IOException 如果读取目录失败
     */
    public static List<File> listDirectories(String dirPath) throws IOException {
        List<File> directories = new ArrayList<>();
        try (DirectoryStream<Path> stream = Files.newDirectoryStream(Paths.get(dirPath))) {
            for (Path path : stream) {
                if (Files.isDirectory(path)) {
                    directories.add(path.toFile());
                }
            }
        }
        return directories;
    }
}